package org.jb.coinche.server.business.transition;

import java.util.Collections;
import java.util.List;

import org.jb.coinche.client.business.message.AddUserMessage;
import org.jb.coinche.client.business.message.NextRoundMessage;
import org.jb.coinche.client.business.message.RemoveUserMessage;
import org.jb.coinche.client.business.model.AuctionTurn;
import org.jb.coinche.client.business.model.Card;
import org.jb.coinche.client.business.model.Game;
import org.jb.coinche.client.business.model.GameState;
import org.jb.coinche.client.business.model.Player;
import org.jb.coinche.client.business.model.RoundFinished;
import org.jb.coinche.client.user.UserLogin;
import org.jb.coinche.server.business.Deck;
import org.jb.coinche.server.business.ColorComparator;
import org.jb.coinche.server.statemachine.Message;
import org.jb.coinche.server.statemachine.Transition;

import com.google.inject.Inject;
import com.google.inject.Provider;

/*
 * Transition faisant debuter une partie
 */
public class GameReadyTransition implements Transition {

	@Inject @UserLogin
	private Provider<String> user;
	
	/*
	 * On est pres lorsque les joueurs ont rejoint la table
	 */
	@Message
	public Object process( Game game, AddUserMessage msg ) {
		
		String userName = user.get();
		
		game.addUser( userName, msg.getIndex() );
		
		if (!game.isWaiting()) {
			return createAuctionTurn( game );
		} else
			return game;
	}
	
	@Message
	public Game process( GameState gameState, RemoveUserMessage msg ) {

		if (!gameState.getGame().removeUser( user.get() ))
			return null;
		
		return gameState.getGame();
	}
	
	/*
	 * On relance un round
	 */
	@Message
	public AuctionTurn processNextRound( RoundFinished rf, NextRoundMessage msg ) {
		
		return createAuctionTurn( rf.getGame() );
		
	}
	
	/**
	 * 
	 * @param game
	 * @return
	 */
	private AuctionTurn createAuctionTurn( Game game ) {
		
		distribute( game );
		
		game.setDealer( game.getNextPlayer( game.getDealer() ) );
		
		AuctionTurn turn = new AuctionTurn();
		turn.setGame( game );
		turn.setWaitingPlayer( game.getNextPlayer(game.getDealer()) );
		
		return turn;
		
	}
	
	/*
	 * distribution des cartes
	 */
	public static void distribute( Game g ) {
		
		// Suppression des cartes
		for( Player p : g.getPlayers() ) {
			p.getCards().clear();
		}
		
		Deck cardsBag = new Deck();
		
		// Distribution
		for( int i = 0; i < 8; ++i ) {
			for( Player p : g.getPlayers() ) {
				p.getCards().add( cardsBag.getCard() );
			}
		}
		
		for( Player p : g.getPlayers() ) {
			sort( p.getCards() );
		}
	}
	
	/*
	 * Tri basique, par couleur
	 */
	public static void sort( List<Card> cards ) {
		Collections.sort( cards, new ColorComparator() );
	}
}
